package com.shsoft.task;

import com.shsoft.entity.HardWareInfo;
import com.shsoft.util.WinRing0Util;
import oshi.hardware.CentralProcessor;
import oshi.hardware.HardwareAbstractionLayer;

public class CpuTask implements Runnable{

    @Override
    public void run() {
        HardwareAbstractionLayer hardware = HardWareInfo.systemInfo.getHardware();
        CentralProcessor processor = hardware.getProcessor();
        CentralProcessor.ProcessorIdentifier identifier = processor.getProcessorIdentifier();
        HardWareInfo.cpuName = identifier.getName();
        HardWareInfo.cpuBaseClock = (int) (processor.getMaxFreq() / 1000000);
        while (true){
            long[] prevTicks = processor.getSystemCpuLoadTicks();
            long startTime = 0;
            long startEnergy = 0;
            if(HardWareInfo.cpuName.contains("Core")){
                startTime = System.currentTimeMillis();
                startEnergy = WinRing0Util.getCpuEnergy();
            }
            try {
                Thread.sleep(1400);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long[] ticks = processor.getSystemCpuLoadTicks();
            long endTime = System.currentTimeMillis();
            long endEnergy = WinRing0Util.getCpuEnergy();
            long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
            long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
            long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
            long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
            long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
            long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
            long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
            long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
            long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
            if(HardWareInfo.cpuName.contains("Core")){
                HardWareInfo.cpuTempCur = WinRing0Util.getCpuTemperature();
                float sec = (endTime - startTime) / 1400.0f;
                long energy;
                if(endEnergy >= startEnergy){
                    energy = endEnergy - startEnergy;
                }else {
                    energy = (1 << 32) + (endEnergy - startEnergy);
                }
                float cpuCpuEnergyUnit = WinRing0Util.getCpuEnergyUnit();
                HardWareInfo.cpuPowerCur = (energy * cpuCpuEnergyUnit) / sec;
                HardWareInfo.cpuClockCur = (int) (WinRing0Util.getPerfStatus() * 100);
            }
            HardWareInfo.cpuUsageCur = (int) (100 - (idle * 100) / totalCpu);
            // 刷新最大值、最小值
            if(HardWareInfo.cpuTempMin == 0 || HardWareInfo.cpuTempMin > HardWareInfo.cpuTempCur){
                HardWareInfo.cpuTempMin = HardWareInfo.cpuTempCur;
            }
            if(HardWareInfo.cpuTempMax == 0 || HardWareInfo.cpuTempMax < HardWareInfo.cpuTempCur){
                HardWareInfo.cpuTempMax = HardWareInfo.cpuTempCur;
            }
            if(HardWareInfo.cpuPowerMin == 0 || HardWareInfo.cpuPowerMin > HardWareInfo.cpuPowerCur){
                HardWareInfo.cpuPowerMin = HardWareInfo.cpuPowerCur;
            }
            if(HardWareInfo.cpuPowerMax == 0 || HardWareInfo.cpuPowerMax < HardWareInfo.cpuPowerCur){
                HardWareInfo.cpuPowerMax = HardWareInfo.cpuPowerCur;
            }
            if(HardWareInfo.cpuClockMin == 0 || HardWareInfo.cpuClockMin > HardWareInfo.cpuClockCur){
                HardWareInfo.cpuClockMin = HardWareInfo.cpuClockCur;
            }
            if(HardWareInfo.cpuClockMax == 0 || HardWareInfo.cpuClockMax < HardWareInfo.cpuClockCur){
                HardWareInfo.cpuClockMax = HardWareInfo.cpuClockCur;
            }
            if(HardWareInfo.cpuUsageMin == 0 || HardWareInfo.cpuUsageMin > HardWareInfo.cpuUsageCur){
                HardWareInfo.cpuUsageMin = HardWareInfo.cpuUsageCur;
            }
            if(HardWareInfo.cpuUsageMax == 0 || HardWareInfo.cpuUsageMax < HardWareInfo.cpuUsageCur){
                HardWareInfo.cpuUsageMax = HardWareInfo.cpuUsageCur;
            }
        }
    }
}
